package io.github.leon406.view.button

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Rect
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import io.github.leon406.ext.radius
import me.leon.ui.R

class LLGradientDrawable : GradientDrawable() {
    private var _adjustBound = false
    private var _fillColors: ColorStateList? = null
    private var _strokeColors: ColorStateList? = null
    private var _strokeWidth = 0

    /** 设置按钮的背景色(只支持纯色,不支持 Bitmap 或 Drawable) */
    fun setBgData(colors: ColorStateList?) {
        super.setColor(colors)
        _fillColors = colors
    }

    /** 设置按钮的描边粗细和颜色 */
    fun setStrokeData(width: Int, colors: ColorStateList?) {
        _strokeWidth = width
        _strokeColors = colors
        super.setStroke(width, colors)
    }

    /** 设置圆角大小是否自动适应为 View 的高度的一半 */
    fun setIsRadiusAdjustBounds(isRadiusAdjustBounds: Boolean) {
        _adjustBound = isRadiusAdjustBounds
    }

    override fun isStateful() =
        _fillColors?.isStateful ?: false || _strokeColors?.isStateful ?: false || super.isStateful()

    override fun onBoundsChange(r: Rect?) {
        super.onBoundsChange(r)
        if (_adjustBound) {
            cornerRadius = (r!!.width().coerceAtMost(r.height()) / 2).toFloat()
        }
    }

    override fun onStateChange(stateSet: IntArray?): Boolean {
        var isChange = super.onStateChange(stateSet)
        _fillColors?.run {
            setColor(getColorForState(stateSet, 0))
            isChange = true
        }
        _strokeColors?.run {
            setStroke(_strokeWidth, getColorForState(stateSet, 0))
            isChange = true
        }
        return isChange
    }

    companion object {

        private fun obtainDrawable(drawable: LLGradientDrawable?): LLGradientDrawable =
            drawable ?: LLGradientDrawable()

        fun fromAttribute(
            context: Context,
            attributes: AttributeSet?,
            defaultStyle: Int
        ): LLGradientDrawable? {
            var drawable: LLGradientDrawable? = null
            context
                .obtainStyledAttributes(attributes, R.styleable.RoundButton, defaultStyle, 0)
                .apply {
                    val borderWidth = getDimension(R.styleable.RoundButton_border, 0f)
                    var adjustRadius = getBoolean(R.styleable.RoundButton_is_half_radius, false)
                    val cornerRadiusAll = getDimension(R.styleable.RoundButton_corner_radius, 0f)
                    val borderColor = getColorStateList(R.styleable.RoundButton_border_color)
                    val bgColor = getColorStateList(R.styleable.RoundButton_bg_color)
                    val topLeftRadius =
                        getDimension(R.styleable.RoundButton_corner_radius_top_left, 0f)
                    val topRightRadius =
                        getDimension(R.styleable.RoundButton_corner_radius_top_right, 0f)
                    val bottomLeftRadius =
                        getDimension(R.styleable.RoundButton_corner_radius_bottom_left, 0f)
                    val bottomRightRadius =
                        getDimension(R.styleable.RoundButton_corner_radius_bottom_right, 0f)

                    if (topLeftRadius != 0f ||
                            topRightRadius != 0f ||
                            bottomLeftRadius != 0f ||
                            bottomRightRadius != 0f
                    ) {
                        drawable = obtainDrawable(drawable)
                        drawable!!.radius(
                            topLeftRadius,
                            topRightRadius,
                            bottomRightRadius,
                            bottomLeftRadius
                        )
                        adjustRadius = false
                    }

                    if (cornerRadiusAll != 0f) {
                        drawable = obtainDrawable(drawable)
                        drawable!!.radius(cornerRadiusAll)
                    }
                    if (adjustRadius) {
                        drawable = obtainDrawable(drawable)
                        drawable!!.setIsRadiusAdjustBounds(adjustRadius)
                    }
                    drawable?.run {
                        setStrokeData(borderWidth.toInt(), borderColor)
                        setBgData(bgColor)
                    }
                }
                .recycle()

            return drawable
        }
    }
}
